home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
User's Choice Windows CD
/
User's Choice Windows CD (CMS Software)(1993).iso
/
windows3
/
mdit.zip
/
MDIT_SRC.ZIP
/
THREAD.C
< prev
Wrap
C/C++ Source or Header
|
1992-03-31
|
11KB
|
325 lines
/****************************************************************************
Module name: MDIT.C
Programmer : Jeffrey M. Richter & Elvira Peretsman.
Modified : V. M. Vanderburg & M.T. Peterson, TriTechnologies
- Converted to multithreading
- Removed original comments
ATTRIBUTIONS:
With the exception of the PCthread calls, this code was taken directly
from the source disk furnished with the Windows Developer's Guide,
M&T Press, by Jeffrey M. Richter. I highly recommend Mr. Richter's
book both for its readability and the structure and quality of the
code.
*****************************************************************************/
/*
#include "..\nowindws.h"
#undef NOCOLOR
#undef NOGDI
#undef NOKERNEL
#undef NOLSTRING
#undef NOMB
#undef NOMDI
#undef NOMENUS
#undef NOUSER
#undef NOWINMESSAGES
#undef NOWINOFFSETS
*/
#include <windows.h>
#include "mdit.h" /* includes pcthread.h */
#include <errno.h>
#include <except.h>
extern pcthread_attr_t g_th_attr;
static char _szClassName[] = "Thread";
typedef struct
{
HMENU hMenu;
HANDLE hAccelTable;
pcthread_t *pcth_p;
} CLSEB;
/************************* Drawing routines ****************************/
static void DrawRectangle( HWND hwnd )
{
HBRUSH hBrush;
HDC hdc;
RECT r;
short xLeft, xRight, yTop, yBottom, nRed, nGreen, nBlue;
GetClientRect( hwnd, &r );
if( (r.right == 0) || (r.bottom == 0) )
return;
xLeft = rand() % r.right;
xRight = rand() % r.right;
yTop = rand() % r.bottom;
yBottom = rand() % r.bottom;
nRed = rand() & 255;
nGreen = rand() & 255;
nBlue = rand() & 255;
hdc = GetDC( hwnd );
hBrush = CreateSolidBrush( RGB(nRed, nGreen, nBlue) );
SelectObject(hdc, hBrush );
Rectangle(hdc, min(xLeft, xRight), min(yTop, yBottom),
max(xLeft, xRight), max(yTop, yBottom) );
ReleaseDC(hwnd, hdc);
DeleteObject(hBrush);
}
/*-------------------------------------------------------------------*/
/* DrawLoop() */
/*-------------------------------------------------------------------*/
/* ACTION: */
/* */
/* This is the function that is passed to the pcthread_create() */
/* routine and is known as the thread action routine. Each thread */
/* executes this loop over and over until it is cancelled or the */
/* application terminates. */
/* */
/* In this loop, each thread draws a single rectangle in the child */
/* window it 'owns' and then yields control to any other threads */
/* that are waiting on the thread ready queue -- Hence the name */
/* pcthread_yield(). */
/*-------------------------------------------------------------------*/
void FAR DrawLoop(pcthread_addr_t parameter)
{
HWND hwnd;
hwnd = (HWND) parameter;
for (;;)
{
DrawRectangle(hwnd);
pcthread_yield();
pcthread_testcancel();
}
}
/************************** Child Message Loop ****************************/
LONG FAR PASCAL ThreadProc (HWND hWnd, WORD wMsg, WORD wParam, LONG lParam) {
BOOL fCallDefProc = FALSE;
DWORD dwResult = 0;
WORD wTemp = 0;
HMENU hMenu;
char szBuf[100], szString[100], szCaption[25];
pcthread_t *th_p;
int stat;
switch (wMsg)
{
case WM_CREATE:
if (GETCLSEB(hWnd, CLSEB, hMenu) == NULL)
{
wTemp = LoadMenu(g_hInstance, _szClassName);
SETCLSEB(hWnd, CLSEB, hMenu, (HMENU) wTemp);
wTemp = LoadAccelerators(g_hInstance, _szClassName);
SETCLSEB(hWnd, CLSEB, hAccelTable, (HANDLE) wTemp);
}
th_p = (pcthread_t *) pcthread_malloc_np(sizeof(pcthread_t));
if (th_p == NULL)
{
MessageBox(hWnd, "Out of memory.", g_szAppName, MB_OK);
break;
}
/*
* -- Create a child thread that is to execute the
* DrawLoop() function. If the call fails for
* any reason, a -1 will be returned in which case
* we try to gracefully terminate the application.
*/
stat = pcthread_create(th_p,
g_th_attr,
(pcthread_action_t) DrawLoop,
(pcthread_addr_t *) hWnd);
if( stat < 0 )
pcthread_shutdown_np("","",
"pcthread_create() failed",
client_exception_e );
/*
* -- The pcthread_detach() call instructs the thread
* kernel to recover and reutilize the memory and other
* objects (mutexes and condition variables) from which
* the thread was created. Threads that are not detached
* hang around until the application terminates.
*
* Why not detach all threads? Well, because there is
* another service called pcthread_join() that allows you
* to obtain the return values, if any, from the thread's
* action routine. In this application, there are none so
* we might as well detach 'em immediately.
*/
stat = pcthread_detach(th_p);
if( stat < 0 )
pcthread_shutdown_np("","",
"pcthread_detach() failed",
client_exception_e );
/*
* -- This 'attaches' the thread's handle, th_p, to a
* specific window.
*/
SetWindowWord( hWnd, 0, (WORD) th_p);
break;
case WM_MDIACTIVATE:
if (wParam == FALSE) break;
ChangeMDITMenu(GETFRAME(hWnd), GetParent(hWnd),
(HMENU) GETCLSEB(hWnd, CLSEB, hMenu), IDM_WINDOWTILEVERT);
g_hAccelTable = (HANDLE) GETCLSEB(hWnd, CLSEB, hAccelTable);
InvalidateRect(GETFRAME(hWnd), NULL, TRUE);
break;
case WM_CLOSE:
fCallDefProc = TRUE;
SendMessage(hWnd, WM_ENDSESSION, TRUE, 0);
break;
case WM_QUERYENDSESSION:
dwResult = TRUE;
break;
case WM_ENDSESSION:
break;
case WM_DESTROY:
/*
* -- Here we obtain the handle of the thread associated
* with the window being cancelled. As a multithreaded
* program, we have to remember to cancel the thread
* as well as destroy the child window.
*/
th_p = (pcthread_t *) GetWindowWord(hWnd, 0 );
PostMessage(GETFRAME(hWnd), FW_MDITCHILDDESTROY, hWnd, 0);
fCallDefProc = TRUE;
if (th_p != NULL)
pcthread_cancel( *th_p );
break;
case AC_PAINTSTATBAR:
LoadString(g_hInstance, IDS_THREADSTATUSBAR, szBuf, sizeof(szBuf));
((LPPAINTSTRUCT) lParam)->rcPaint.top += (int)
SendMessage(GETFRAME(hWnd), FW_DRAWSTATUSDIVIDE, 0,
(LONG) (LPPAINTSTRUCT) lParam);
TextOut((HDC) wParam, 0, ((LPPAINTSTRUCT) lParam)->rcPaint.top,
szBuf, lstrlen(szBuf));
break;
case WM_MENUSELECT:
if (lParam == MAKELONG(-1, 0))
{
SendMessage(GETFRAME(hWnd), FW_SETMENUHELP, 0, 0);
break;
}
switch (LOWORD(lParam) & (MF_POPUP | MF_SYSMENU))
{
case 0:
if ((wParam > IDM_WINDOWCHILD) && (wParam <= IDM_WINDOWCHILD + 9))
wParam = IDM_WINDOWCHILD;
wTemp = IDS_THREADMENUID + wParam;
break;
case MF_POPUP:
hMenu = GetMenu(GETFRAME(hWnd));
wTemp = GetMenuItemCount(hMenu);
while (wTemp--)
if (GetSubMenu(hMenu, wTemp) == (HMENU) wParam) break;
wTemp += IDS_THREADPOPUPID;
if (!IsZoomed(hWnd)) wTemp++;
break;
case MF_SYSMENU:
wTemp = IDS_THREADMENUID + ((wParam & 0x0FFF) >> 4);
break;
case MF_POPUP | MF_SYSMENU:
wTemp = IDS_THREADPOPUPID;
break;
}
SendMessage(GETFRAME(hWnd), FW_SETMENUHELP, hWnd, wTemp);
break;
case WM_ENTERIDLE:
SendMessage(GETFRAME(hWnd), wMsg, wParam, lParam);
break;
case AW_PAINTMENUHELP:
dwResult = SendMessage(GETFRAME(hWnd), FW_GETMENUHELP, 0, 0);
((LPPAINTSTRUCT) lParam)->rcPaint.top += (int)
SendMessage(GETFRAME(hWnd), FW_DRAWSTATUSDIVIDE, 0,
(LONG) (LPPAINTSTRUCT) lParam);
LoadString(g_hInstance, LOWORD(dwResult), szString, sizeof(szString));
GetWindowText(hWnd, szCaption, sizeof(szCaption));
wsprintf(szBuf, szString, (LPSTR) szCaption);
TextOut(((LPPAINTSTRUCT) lParam)->hdc,
0, ((LPPAINTSTRUCT) lParam)->rcPaint.top, szBuf, lstrlen(szBuf));
break;
case WM_COMMAND:
MessageBox(hWnd, "Option not implemented.", g_szAppName, MB_OK);
break;
default: fCallDefProc = TRUE; break;
}
if (fCallDefProc)
dwResult = DefMDIChildProc(hWnd, wMsg, wParam, lParam);
return(dwResult);
}
BOOL FAR PASCAL RegisterThreadWndClass (void)
{
WNDCLASS wc;
wc.style = 0;
wc.lpfnWndProc = ThreadProc;
wc.cbClsExtra = sizeof(CLSEB);
wc.cbWndExtra = 0;
wc.hInstance = g_hInstance;
wc.hIcon = LoadIcon(g_hInstance, _szClassName);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = COLOR_WINDOW + 1;
wc.lpszMenuName = NULL;
wc.lpszClassName = _szClassName;
return(RegisterClass(&wc));
}